package org.sql.jdbc.param;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.sql.jdbc.field.FieldTag;
import org.sql.jdbc.table.TableTag;

/** 
 * jdbc操作对象 
 *
 * <pre> 
 * 构建组：e-jdbc
 * 作者：eddy
 * 邮箱：1546077710@qq.com
 * 日期：2017年4月23日-下午9:51:55
 * 版权：E源时代
 * </pre>
 */
public class Operator {

	/***
	 * 主键字符串
	 */
	public Param prikey;
	/**
	 * 数据字段字符串
	 */
	public List<Param> fieldLis;
	/**
	 * 数据表名
	 */
	public String tabName;

	public Operator(Object obj){
		parseFields(obj);
		parseTabName(obj);
		parsePrimaryKey(obj);
	}
	
	public Operator(Class<?> obj){
		parseFields(obj);
		parseTabName(obj);
		parsePrimaryKey(obj);
	}
	
	public Param getPrikey() {
		return prikey;
	}

	public void setPrikey(Param prikey) {
		this.prikey = prikey;
	}

	public List<Param> getFieldLis() {
		return fieldLis;
	}

	public void setFieldLis(List<Param> fieldLis) {
		this.fieldLis = fieldLis;
	}

	public String getTabName() {
		return tabName;
	}

	public void setTabName(String tabName) {
		this.tabName = tabName;
	}

	/**
	 * 获取数据字段对应键值对
	 *
	 * @param obj	操作对象
	 * @throws Exception 
	 */
	public void parseFields(Object obj){
		fieldLis = new ArrayList<Param>();
		try {
			Class<?> clas = Class.forName(obj.getClass().getName());
			// 获取表名
			Annotation[] tabAnns = clas.getDeclaredAnnotations();
			if (null != tabAnns && tabAnns.length > 0) {
				for (Annotation ann : tabAnns) {
					tabName = ((TableTag) ann).tabName();
				}
			}
			// 获取所有成员变量
			Field[] fields = clas.getDeclaredFields();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] fieldAnns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != fieldAnns && fieldAnns.length > 0) {
					for (Annotation ann : fieldAnns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						Boolean primaryKey = ((FieldTag) ann).pk();
						// 获取字段的get方法
						StringBuffer fieldStr = new StringBuffer(
								"get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
						Method fieldMethod = clas.getMethod(fieldStr.toString(), new Class[] {});
						Object fieldValue = fieldMethod.invoke(obj, new Object[] {});
						String fieldType = field.getType().getName();
						// 判断值是否存在
						if (null != fieldValue) {
							if (null != primaryKey && primaryKey == true) {
								prikey = new Param(fieldName, fieldType, fieldValue.toString());
							} else {
								fieldLis.add(new Param(fieldName, fieldType, fieldValue.toString()));
							}
						} else {
							if (null != primaryKey && primaryKey == true) {
								prikey = new Param(fieldName, fieldType, "");
							}
						}
					}
				}
			}
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("类名不存在!");
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		}
	}

	/**
	 * 获取数据字段对应键值对
	 *
	 * @param obj	操作对象
	 * @throws Exception 
	 */
	public void parseFields(Class<?> obj) {
		fieldLis = new ArrayList<Param>();
		try {
			// 获取表名
			Annotation[] tabAnns = obj.getDeclaredAnnotations();
			if (null != tabAnns && tabAnns.length > 0) {
				for (Annotation ann : tabAnns) {
					tabName = ((TableTag) ann).tabName();
				}
			}
			// 获取所有成员变量
			Field[] fields = obj.getDeclaredFields();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] fieldAnns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != fieldAnns && fieldAnns.length > 0) {
					for (Annotation ann : fieldAnns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						Boolean primaryKey = ((FieldTag) ann).pk();
						// 获取字段的get方法
						StringBuffer fieldStr = new StringBuffer(
								"get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
						Method fieldMethod = obj.getMethod(fieldStr.toString(), new Class[] {});
						Object fieldValue = fieldMethod.invoke(obj, new Object[] {});
						String fieldType = field.getType().getName();
						// 判断值是否存在
						if (null != fieldValue) {
							if (null != primaryKey && primaryKey == true) {
								prikey = new Param(fieldName, fieldType, fieldValue.toString());
							} else {
								fieldLis.add(new Param(fieldName, fieldType, fieldValue.toString()));
							}
						} else {
							if (null != primaryKey && primaryKey == true) {
								prikey = new Param(fieldName, fieldType, "");
							}
						}
					}
				}
			}
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		}
	}

	/**
	 * 获取对象对应数据表名
	 *
	 * @param obj
	 * @throws Exception 
	 */
	public void parseTabName(Object obj) {
		try {
			Class<?> clas = Class.forName(obj.getClass().getName());
			Annotation[] anns = clas.getDeclaredAnnotations();
			if (null != anns && anns.length > 0) {
				for (Annotation ann : anns) {
					tabName = ((TableTag) ann).tabName();
				}
			}
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("类名不存在!");
		}
	}

	/**
	 * 获取对象对应数据表名
	 *
	 * @param obj
	 * @throws Exception 
	 */
	public void parseTabName(Class<?> obj) {
		try {
			Annotation[] anns = obj.getDeclaredAnnotations();
			if (null != anns && anns.length > 0) {
				for (Annotation ann : anns) {
					tabName = ((TableTag) ann).tabName();
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("类名不存在!");
		}
	}

	/**
	 * 获取主键键值对
	 *
	 * @param obj
	 * @throws Exception 
	 */
	public void parsePrimaryKey(Object obj) {
		try {
			Class<?> clas = Class.forName(obj.getClass().getName());
			// 获取所有成员变量
			Field[] fields = clas.getDeclaredFields();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] anns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != anns && anns.length > 0) {
					for (Annotation ann : anns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						Boolean primaryKey = ((FieldTag) ann).pk();
						// 是否为主键
						if (null != primaryKey && primaryKey == true) {
							// 获取字段的get方法
							StringBuffer fieldStr = new StringBuffer("get"
									+ field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
							Method fieldMethod = clas.getMethod(fieldStr.toString(), new Class[] {});
							Object fieldValue = fieldMethod.invoke(obj, new Object[] {});
							String fieldType = field.getType().getName();
							// 判断值是否存在
							if (null != fieldValue) {
								prikey = new Param(fieldName, fieldType, fieldValue.toString());
							}
						}
					}
				}
			}
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("类名不存在!");
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		}
	}

	/**
	 * 获取主键键值对
	 *
	 * @param obj
	 * @throws Exception 
	 */
	public void parsePrimaryKey(Class<?> obj) {
		try {
			// 获取所有成员变量
			Field[] fields = obj.getDeclaredFields();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] anns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != anns && anns.length > 0) {
					for (Annotation ann : anns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						Boolean primaryKey = ((FieldTag) ann).pk();
						// 是否为主键
						if (null != primaryKey && primaryKey == true) {
							// 获取字段的get方法
							StringBuffer fieldStr = new StringBuffer("get"
									+ field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
							Method fieldMethod = obj.getMethod(fieldStr.toString(), new Class[] {});
							Object fieldValue = fieldMethod.invoke(obj, new Object[] {});
							String fieldType = field.getType().getName();
							// 判断值是否存在
							if (null != fieldValue) {
								prikey = new Param(fieldName, fieldType, fieldValue.toString());
							}
						}
					}
				}
			}
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		}
	}

	/**
	 * 获取对应对象数组
	 *
	 * @param obj
	 * @param rs
	 * @return
	 * @throws Exception 
	 */
	public static List<?> toList(Object obj, ResultSet rs) {
		List<Object> lisObj = new ArrayList<Object>();
		try {
			Class<?> clas = Class.forName(obj.getClass().getName());
			// 获取所有成员变量
			Field[] fields = clas.getDeclaredFields();

			List<Method> methodList = new ArrayList<Method>();
			List<String> lisFields = new ArrayList<String>();
			List<String> fileTypes = new ArrayList<String>();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] anns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != anns && anns.length > 0) {
					for (Annotation ann : anns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						// set方法获取
						StringBuffer fieldStr = new StringBuffer(
								"set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
						Class<?> fieldType = field.getType();
						Method method = clas.getMethod(fieldStr.toString(), new Class[] { fieldType });
						methodList.add(method);
						lisFields.add(fieldName);
						fileTypes.add(fieldType.getName());
					}
				}
			}
			ResultSetMetaData rsd = rs.getMetaData();
			int columnNum = rsd.getColumnCount();
			while (rs.next()) {
				Object obje = clas.newInstance();
				for (int j = 1; j <= columnNum; j++) {
					String columnName = rsd.getColumnName(j);
					for (int i = 0; i < methodList.size(); i++) {
						String filedName = lisFields.get(i);
						if (columnName.equalsIgnoreCase(filedName)) {
							Method method = methodList.get(i);
							if (fileTypes.get(i).equals("java.sql.Blob")) {
								method.invoke(obje, new Object[] { rs.getBlob(filedName) });
							} else if (fileTypes.get(i).equals("java.lang.Integer")) {
								method.invoke(obje, new Object[] { rs.getInt(filedName) });
							} else if (fileTypes.get(i).equals("java.lang.Double")) {
								method.invoke(obje, new Object[] { rs.getDouble(filedName) });
							} else {
								if (null != rs.getObject(filedName)) {
									method.invoke(obje, new Object[] { rs.getObject(filedName).toString() });
								} else {
									method.invoke(obje, new Object[] { "" });
								}
							}
						}
					}
				}
				lisObj.add(obje);
			}
			return lisObj;
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("类名不存在!");
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (SQLException e) {
			throw new RuntimeException("数据访问出错!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		} catch (InstantiationException e) {
			throw new RuntimeException("实例失败！");
		}
	}

	/**
	 * 获取对应对象数组
	 *
	 * @param obj
	 * @param rs
	 * @return
	 * @throws Exception 
	 */
	public static List<?> toList(Class<?> obj, ResultSet rs) {
		List<Object> lisObj = new ArrayList<Object>();
		try {
			// 获取所有成员变量
			Field[] fields = obj.getDeclaredFields();

			List<Method> methodList = new ArrayList<Method>();
			List<String> lisFields = new ArrayList<String>();
			List<String> fileTypes = new ArrayList<String>();
			// 组装数据库字段、值的键值对
			for (Field field : fields) {
				// 获取注释
				Annotation[] anns = field.getDeclaredAnnotations();
				// 存在注释
				if (null != anns && anns.length > 0) {
					for (Annotation ann : anns) {
						// 字段名
						String fieldName = ((FieldTag) ann).field();
						// set方法获取
						StringBuffer fieldStr = new StringBuffer(
								"set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
						Class<?> fieldType = field.getType();
						Method method = obj.getMethod(fieldStr.toString(), new Class[] { fieldType });
						methodList.add(method);
						lisFields.add(fieldName);
						fileTypes.add(fieldType.getName());
					}
				}
			}
			ResultSetMetaData rsd = rs.getMetaData();
			int columnNum = rsd.getColumnCount();
			while (rs.next()) {
				Object obje = obj.newInstance();
				for (int j = 1; j <= columnNum; j++) {
					String columnName = rsd.getColumnName(j);
					for (int i = 0; i < methodList.size(); i++) {
						String filedName = lisFields.get(i);
						if (columnName.equalsIgnoreCase(filedName)) {
							Method method = methodList.get(i);
							if (fileTypes.get(i).equals("java.sql.Blob")) {
								method.invoke(obje, new Object[] { rs.getBlob(filedName) });
							} else if (fileTypes.get(i).equals("java.lang.Integer")) {
								method.invoke(obje, new Object[] { rs.getInt(filedName) });
							} else if (fileTypes.get(i).equals("java.lang.Double")) {
								method.invoke(obje, new Object[] { rs.getDouble(filedName) });
							} else {
								if (null != rs.getObject(filedName)) {
									method.invoke(obje, new Object[] { rs.getObject(filedName).toString() });
								} else {
									method.invoke(obje, new Object[] { "" });
								}
							}
						}
					}
				}
				lisObj.add(obje);
			}
			
			return lisObj;
		} catch (SecurityException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("此方法不存在!");
		} catch (SQLException e) {
			throw new RuntimeException("数据访问出错!");
		} catch (IllegalArgumentException e) {
			throw new RuntimeException("对象不是声明类的一个实例!");
		} catch (IllegalAccessException e) {
			throw new RuntimeException("此方法不允许访问!");
		} catch (InvocationTargetException e) {
			throw new RuntimeException("方法错误!");
		} catch (InstantiationException e) {
			throw new RuntimeException("实例失败！");
		}
	}

	/**
	 * 将结果集包装成Map
	 *
	 * @param rs
	 * @return
	 * @throws Exception 
	 */
	public static List<Map<String, Object>> toMapList(ResultSet rs) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		try {
			ResultSetMetaData rsd = rs.getMetaData();
			int columnNum = rsd.getColumnCount();
			while (rs.next()) {
				Map<String, Object> objMap = new HashMap<String, Object>();
				for (int j = 1; j <= columnNum; j++) {
					String columnName = rsd.getColumnName(j);
					Object columnValue = rs.getObject(columnName);
					objMap.put(columnName, columnValue);
				}
				result.add(objMap);
			}
		} catch (Exception e) {
			throw new RuntimeException("数据集转换异常！");
		}
		
		return result;
	}
}
